-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
646 use graph model with ABMs v3 #1085
base: main
Are you sure you want to change the base?
Conversation
…/SciCompMod/memilio into 646-use-graph-model-with-abms-v2
…/SciCompMod/memilio into 646-use-graph-model-with-abms-v2
…/SciCompMod/memilio into 646-use-graph-model-with-abms-v2
…/SciCompMod/memilio into 646-use-graph-model-with-abms-v3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the sophisticated implementation!
In addition to a couple of small things, we should have a more detailed look at two things:
- History embedding in ABM graph simulation
- RNG embedding in ABM graph simulation
Details can be found in the comments.
cpp/examples/graph_abm.cpp
Outdated
model1.parameters.get<mio::abm::IncubationPeriod>() = 4.; | ||
model1.parameters.get<mio::abm::InfectedNoSymptomsToSymptoms>() = 2.; | ||
model1.parameters.get<mio::abm::InfectedNoSymptomsToRecovered>() = 4.; | ||
model1.parameters.get<mio::abm::InfectedSymptomsToRecovered>() = 5.; | ||
model1.parameters.get<mio::abm::InfectedSymptomsToSevere>() = 6.; | ||
model1.parameters.get<mio::abm::SevereToRecovered>() = 8.; | ||
model1.parameters.get<mio::abm::SevereToCritical>() = 7.; | ||
model1.parameters.get<mio::abm::CriticalToRecovered>() = 10.; | ||
model1.parameters.get<mio::abm::CriticalToDead>() = 11.; | ||
|
||
//Age group 0 goes to school and age group 1 goes to work | ||
model1.parameters.get<mio::abm::AgeGroupGotoSchool>()[age_group_children] = true; | ||
model1.parameters.get<mio::abm::AgeGroupGotoWork>()[age_group_adults] = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these are supposed to be for model2?
cpp/models/abm/person_id.h
Outdated
{ | ||
} | ||
|
||
/// @brief Create an invalid ID. | ||
PersonId() | ||
: mio::TypeSafe<uint32_t, PersonId>(std::numeric_limits<uint32_t>::max()) | ||
: mio::TypeSafe<uint64_t, PersonId>(std::numeric_limits<uint32_t>::max()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We quickly talked about the change to 64 bit.
A comment somewhere here would be good to explain that only valid uint32_t values should be used for the Id. Perhaps even an assert in the constructor?
} | ||
|
||
private: | ||
Sim m_simulation; ///< ABM Simulation of the node |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just as a comment:
This is interesting. I would have thought that each node is the Model, not holding a simulation, and that there is only one simulation that determines how to advance globally.
Holding a simulation for each node however allows for (potential) different time steps, and it is in line with the ODE models. (And allows for refined histories, individual results, etc.)
cpp/models/abm/model.cpp
Outdated
mio::abm::add_exposure_contribution(m_air_exposure_rates_cache[location], | ||
m_contact_exposure_rates_cache[location], person, | ||
get_location(person.get_id()), t, dt); | ||
if (person.get_location_model_id() == m_id) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also check with the activeness status here to be consistent?
* @param[in] node ABMSimulationNode to which the functor is applied. | ||
*/ | ||
template <class... History> | ||
void evolve_model(abm::TimePoint t, abm::TimeSpan dt, ABMSimulationNode<History...>& node) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See naming comment above. Perhaps: advance_node
?
struct MockHistory { | ||
|
||
template <class T> | ||
void log(const T& t) | ||
{ | ||
mio::unused(t); | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be omitted if the changes for the history are accepted.
Perhaps one needs to test the alternative advance with a history, though.
graph.add_edge(0, 1); | ||
graph.add_edge(1, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the Ids be used here, too?
cpp/tests/test_graph_abm.cpp
Outdated
EXPECT_EQ(node2.get_simulation().get_model().get_persons().size(), 0); | ||
EXPECT_EQ(node1.get_simulation().get_model().get_persons().size(), 4); | ||
EXPECT_EQ(node1.get_simulation().get_model().get_activeness_statuses()[p2_index], false); | ||
EXPECT_EQ(node1.get_simulation().get_model().get_activeness_statuses()[p4_index], false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One could also check the buffer sizes at this point, perhaps not 100% needed, you can decide.
cpp/models/graph_abm/model_wrapper.h
Outdated
namespace mio | ||
{ | ||
using namespace abm; | ||
class ModelWrapper : public abm::Model |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit unhappy with the naming, as writing ModelWrapper
in the graph initialization is not so nice in my opinion. I'd like this to also be called Model, but of course this is a problem, unless we use a different namespace here. Maybe we can discuss this. Options:
- Keep the name
- Rename namespace to abm_graph or similar
- Rename to Model and rename abm::Model to something else
Co-authored-by: David Kerkmann <[email protected]>
Co-authored-by: David Kerkmann <[email protected]>
cpp/models/abm/person.cpp
Outdated
Person::Person(const Person& other, PersonId id, uint64_t unique_id) | ||
: Person(other) | ||
{ | ||
m_person_id = id; | ||
m_unique_id = unique_id; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we have now two IDs, one of which does not always ID(entify) a person? This needs at least a change in naming or documentation.
As an idea, maybe use local/global in the name of the ID?
Maybe than it could make sense that the global ID defaults to INVALID_ID. And when it is invalid, get_global_id can fall back to the local ID, making them "the same" automatically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a change in naming is a good idea, we can discuss that.
To the second part: If I understand you right, this is exactly what is done in "add_person".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kind of... But I think we should decide either on the World always overwriting the unique ID (like it does with PersonID), or on the World not changing it at all. I feel like changing the ID only when it is invalid can lead to unexpected behaviour, as invalid now means "not set, please overwrite" instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cannot always overwrite it, because when a person changes the world, then it would lose its unique id. What we need to do is only set it, if it has not been set before. I did this using the INVALID_UNIQUE_ID, but I'm open for other solutions :).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the global ID is meant to be set only once, when the person first enters the simulations and is assigned a "home world". For me, this changes make sense. Best would be to have the global ID const, which is initialized during the Person constructor, but this would change the add_person structure. We could make some struct that only allows for a one-time modification and then being const. But there might be better solutions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What we need to do is only set it, if it has not been set before. I did this using the INVALID_UNIQUE_ID
This works now, but the reason we have this invalid id is to signal that something went wrong, hence all the asserts checking for it. If you use it additionally as a "not set" flag, this can potentially end up hiding other problems.
I would be in favor of making it effectively const - an actually const member would be annoying, as we cannot use default move or copy ctors.
Some options would be:
- Setting the UID in main, and removing the UID overwrite from add_person and that Person ctor which copies a Person and assigns a new ID
- using an optional (so we have a "not set" state)
- defining a second value like invalid_id
The latter two options then require checking that the id is both set and valid every time we pass it to a new function. The first requires additional setup outside of the model (which is okay in theory, as it is a "global" id).
All are a bit weird in that we treat the IDs differently. Only one is always being overwritten by the world, the other only sometimes, or elsewhere.
Changes and Information
Please briefly list the changes (main added features, changed items, or corrected bugs) made:
Merge Request - Guideline Checklist
Please check our git workflow. Use the draft feature if the Pull Request is not yet ready to review.
Checks by code author
Checks by code reviewer(s)